package session

import (
	"dmsv/aliyun"
	"dmsv/common"
	"dmsv/ctgw"
	"dmsv/models"
	"encoding/json"
	"github.com/beego/beego/v2/core/logs"
	"strings"
	"time"
)

type rptCallNew struct {
	Event     string `json:"event"`
	CallId    string `json:"callId"`
	AppId     string `json:"appId"`
	Caller    string `json:"caller"`
	Called    string `json:"callee"`
	TimeStamp string `json:"timeStamp"`
	ServiceId string `json:"serviceId"`
	Data      string `json:"data"`
}

func (s *SessionInfo) CallInRpt() {

	msg := rptCallNew{
		Event:     "incomingcall",
		CallId:    s.sessionId,
		Caller:    s.caller,
		Called:    s.callee,
		AppId:     s.appId,
		TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
	}

	data, err := json.Marshal(msg)
	if err != nil {
		logs.Error("[%v] 发送呼入通知失败,json 错误:%v", s.sessionId, err)
		return
	}
	ctgw.SendMessage(gEvtCallBack, data)
}

func (s *SessionInfo) CallOutRpt() {

	msg := rptCallNew{
		Event:     "callout",
		CallId:    s.sessionId,
		Caller:    s.caller,
		Called:    s.callee,
		AppId:     s.appId,
		ServiceId: s.serviceId,
		TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
	}

	data, err := json.Marshal(msg)
	if err != nil {
		logs.Error("[%v] 发送呼入通知失败,json 错误:%v", s.sessionId, err)
		return
	}
	ctgw.SendMessage(gEvtCallBack, data)
}

type rptCallStatus struct {
	Event     string `json:"event"`
	CallId    string `json:"callId"`
	AppId     string `json:"appId"`
	TimeStamp string `json:"timeStamp"`
	ServiceId string `json:"serviceId"`
	IsUser    bool   `json:"isUser"`
	Data      string `json:"data"`
}

func (s *SessionInfo) RingRpt(serviceId string, bUser bool) {

	s.callStatusRpt("ring", serviceId, "", bUser)
}

func (s *SessionInfo) AnswerRpt(serviceId, data string, bUser bool) {

	s.callStatusRpt("answer", serviceId, data, bUser)
}

func (s *SessionInfo) ServiceHangUpRpt(serviceId, data string) {

	s.callStatusRpt("hangup", serviceId, data, false)
}

func (s *SessionInfo) EnQueueRpt(queueId string) {

	msg := rptCallStatus{
		Event:     "enqueue",
		CallId:    s.sessionId,
		AppId:     s.appId,
		Data:      queueId,
		TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
	}

	logs.Debug("[%v] 发送入队通知，当前session队列Id:%v,入队时间:%v", s.sessionId, s.queId, s.enqueTime)
	data, err := json.Marshal(msg)
	if err != nil {
		logs.Error("[%v] 发送呼入通知失败,json 错误:%v", s.sessionId, err)
		return
	}

	ctgw.SendMessage(gEvtCallBack, data)
}

func (s *SessionInfo) callStatusRpt(eventName, serviceId, data string, bUser bool) {

	msg := rptCallStatus{
		Event:     eventName,
		CallId:    s.sessionId,
		AppId:     s.appId,
		ServiceId: serviceId,
		TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
		Data:      data,
		IsUser:    bUser,
	}

	//坐席为外线接听时，

	sendData, err := json.Marshal(msg)
	if err != nil {
		logs.Error("[%v] 发送呼入通知失败,json 错误:%v", s.sessionId, err)
		return
	}

	ctgw.SendMessage(gEvtCallBack, sendData)
}

type billEvent struct {
	Event      string       `json:"event"`
	CallId     string       `json:"callId"`
	AppId      string       `json:"appId"`
	CallType   string       `json:"callType"`
	CallStart  string       `json:"startTime"`
	CallEnd    string       `json:"endTime"`
	MsgTime    string       `json:"msgTime"` //留言时间
	Caller     string       `json:"caller"`
	Callee     string       `json:"callee"`
	TimeStamp  string       `json:"timeStamp"`
	Result     interface{}  `json:"result"`
	Record     string       `json:"record"`
	Score      string       `json:"score"`
	Trajectory string       `json:"trajectory"` //按键轨迹
	QueTrace   queTraceInfo `json:"skill"`
	Detail     []detail     `json:"detail"`
}

func (this *SessionInfo) SaveBill(event billEvent) {

	billInfo := models.IpccBill{
		AppId:      this.appId,
		CallId:     this.sessionId,
		Record:     this.record,
		CallStart:  this.startTime,
		AnswerTime: this.answerTime,
		Service:    this.serviceId,
		Caller:     this.caller,
		Callee:     this.callee,
		Number:     this.display,
	}

	for _, detail := range event.Detail {

		if detail.IsUser {
			billInfo.UserDuration = uint(detail.Dutation)
		} else {
			billInfo.Duration = uint(detail.Dutation)
		}
	}

	models.InsertBill(billInfo)
}

func (this *SessionInfo) SendBill(url string, res interface{}) {

	callStart := this.startTime.Format("2006-01-02 15:04:05")
	callEnd := ""
	dtls := make([]detail, 0, 0)

	if this.hangUpReason != nil {

		switch this.hangUpReason.(type) {
		case common.StatusCode:
			res = this.hangUpReason
		case HangStatus:
			switch this.hangUpReason.(HangStatus) {
			case HANG_UP_API:
				res = common.SuccHangByApi
			default:
				res = common.ErrSystem
			}
		default:
			res = common.ErrSystem
		}
	}

	skillInfo := queTraceInfo{
		QueId:     this.queId,
		EnqueTime: this.enqueTime.Format("2006-01-02 15:04:05"),
	}

	if this.enqueTime.IsZero() {
		skillInfo.EnqueTime = ""
	}

	for _, c := range this.call {

		if c.IsUser() {
			//结束时间以用户挂断为节点
			callEnd = c.EndTime.Format("2006-01-02 15:04:05")
			if len(this.call) == 1 {
				c.ServiceId = this.serviceId
			}
		}

		logs.Debug("[%v] 用户 [%v] 挂机原因:%v", this.sessionId, c.IsUser(), c.HangUpReason)
		if this.callType == CALL_TYPE_IN {
			//开始时间，呼入以用户侧为开始，呼出以坐席侧为开始
			if c.IsUser() {
				callStart = c.StartTime.Format("2006-01-02 15:04:05")
			}
		} else {
			if !c.IsUser() {
				callStart = c.StartTime.Format("2006-01-02 15:04:05")
			}
		}

		d := detail{
			Caller:     c.Caller,
			Callee:     c.Callee,
			SipCode:    c.HangupSipCode,
			Dutation:   c.CallTime,
			ServiceId:  c.ServiceId,
			IsPstn:     c.IsPstn(),
			IsUser:     c.IsUser(),
			CallTime:   c.StartTime.Format("2006-01-02 15:04:05"),
			AnswerTime: c.AnswerTime.Format("2006-01-02 15:04:05"),
		}

		if c.StartTime.IsZero() {
			d.CallTime = c.CreateTime.Format("2006-01-02 15:04:05")
		}

		if c.AnswerTime.IsZero() {
			d.AnswerTime = ""
		}

		dtls = append(dtls, d)
	}

	//https 认为已上传成功
	if false == strings.HasPrefix(this.record, "https") {
		if common.FileIsExist(this.record) {
			this.record = aliyun.UpLoadFile(this.appId, this.sessionId, this.record)
		} else {
			logs.Error("[%v] 无录音文件 ", this.sessionId)
			this.record = ""
		}
	}

	bill := billEvent{
		Event:      "billrpt",
		CallId:     this.sessionId,
		Caller:     this.caller,
		Callee:     this.callee,
		CallType:   string(this.callType),
		TimeStamp:  time.Now().Format("2006-01-02 15:04:05"),
		CallStart:  callStart,
		CallEnd:    callEnd,
		Trajectory: this.dtmf,
		Record:     this.record,
		Score:      this.satisfaction,
		Detail:     dtls,
		Result:     res,
		AppId:      this.appId,
		QueTrace:   skillInfo,
		MsgTime:    this.leaveMsgTime.Format("2006-01-02 15:04:05"),
	}

	if this.leaveMsgTime.IsZero() {
		bill.MsgTime = ""
	}

	msg, err := json.Marshal(bill)
	if err != nil {
		logs.Error("%v bill json wrong:%v", this.sessionId, err)
		return
	}

	ctgw.SendMessage(url, msg)
	this.SaveBill(bill)
}
